package com.yc.mybatis.core;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class SqlSession {
	private ConnectionPool connectionPool;
	private Map<String, MapperInfo> mapperInfos;

	public SqlSession(ConnectionPool connectionPool, Map<String,MapperInfo> mapperInfos) {
		this.connectionPool = connectionPool;
		this.mapperInfos = mapperInfos;
	}

	/**
	 * 更新操作
	 * @param sqlId
	 * @param obj
	 * @return
	 */

	public int update(String sqlId, Object obj) {
		MapperInfo mapperInfo = mapperInfos.getOrDefault(sqlId,  null);

		if(mapperInfo == null) {
			throw new RuntimeException("没有您要执行的" + sqlId + "...");
		}

		int result = -1; 
		Connection con = null;


		try {
			String sql = mapperInfo.getSql(); //获取要执行的SQL语句
			List<String> params = mapperInfo.getParams(); //获取SQL语句中的参数
			List<Object> paramsValues = this.getParamsValue(mapperInfo.getParameterType(), params, obj);

			DBHelper db = new DBHelper();
			con = connectionPool.getConnection();
			result = db.update(con, sql, paramsValues);
			System.out.println(paramsValues);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			if(con != null) {
				this.close(con);
			}
		}

		return -1;
	}

	private void close(Connection con) {
		connectionPool.freeConnection(con);

	}

	/**
	 * 获取参数
	 * @param parameterType
	 * @param params
	 * @param obj
	 * @return
	 * @throws ClassNotFoundException 
	 * @throws InvocationTargetException 
	 * @throws IllegalArgumentException 
	 * @throws IllegalAccessException 
	 */
	@SuppressWarnings("unchecked")
	private List<Object> getParamsValue(String parameterType, List<String> paramsName, Object obj) throws ClassNotFoundException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		if(paramsName == null || paramsName.isEmpty()) { //说明SQL语句没有占位符
			return Collections.emptyList();
		}

		List<Object> params = new ArrayList<Object>();
		if("int".equals(parameterType) || "float".equals(parameterType) || "double".equals(parameterType)|| 
				"string".equals(parameterType)|| "Intger".equals(parameterType)) {
			params.add(obj);
			return params;
		}

		if("map".equals(parameterType)) {
			Map<String, Object> map = (Map<String, Object>) obj;
			for(String name : paramsName) {
				params.add(map.getOrDefault(name, ""));
			}
			return params;
		}

		//如果是类
		Class<?> clazz = Class.forName(parameterType);
		Method[] methods = clazz.getDeclaredMethods();
		//获取getter方法
		String methodName = null;
		Map<String, Method> getters = new HashMap<String, Method>();
		for(Method method : methods) {
			methodName = method.getName();
			if(methodName.startsWith("get")) {
				getters.put(methodName, method);
			}
		}
		Method method = null;
		for(String name : paramsName) {
			//当属性名的第一个字母大写后，在最前面加上get
			methodName = "get" + name.substring(0, 1).toUpperCase() + name.substring(1);
			method = getters.get(methodName);
			if(method == null) {
				params.add(null);
				continue;
			}
			params.add(method.invoke(obj)); //激活给定对象的这个方法，获返回值
		}
		return params;
	}

	@SuppressWarnings("unchecked")
	public <T> List<T> selelctList(String sqlId, Object obj){
		MapperInfo mapperInfo = mapperInfos.getOrDefault(sqlId,  null);

		if(mapperInfo == null) {
			throw new RuntimeException("没有您要执行的" + sqlId + "...");
		}

		Connection con = null;
		try {
			String sql = mapperInfo.getSql(); //获取要执行的SQL语句
			List<String> params = mapperInfo.getParams(); //获取SQL语句中的参数
			List<Object> paramsValues = this.getParamsValue(mapperInfo.getParameterType(), params, obj);

			DBHelper db = new DBHelper();
			con = connectionPool.getConnection();

			if("map".equals(mapperInfo.getResultType())) { //说明要返回的是map
				return (List<T>) db.findMutile(con, sql, paramsValues);
			}

			Class<?> cls = Class.forName(mapperInfo.getResultType());
			return db.findMutile(con, cls, sql, paramsValues);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			if(con != null) {
				this.close(con);
			}
		}
		return Collections.emptyList();
	}


}
